package cn.iocoder.yudao.module.system.service.user;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.infra.api.area.AreaApi;
import cn.iocoder.yudao.module.infra.api.area.dto.AreaDto;
import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.infra.api.maputil.MapUtilApi;
import cn.iocoder.yudao.module.infra.api.maputil.dto.AreaSiteMapDto;
import cn.iocoder.yudao.module.infra.api.maputil.dto.AreaSiteNameMapDto;
import cn.iocoder.yudao.module.infra.api.site.SiteApi;
import cn.iocoder.yudao.module.infra.api.site.dto.SiteDto;
import cn.iocoder.yudao.module.infra.api.ticket.TicketApi;
import cn.iocoder.yudao.module.infra.api.ticket.dto.TicketDto;
import cn.iocoder.yudao.module.infra.api.ymconnection.YmConnectionApi;
import cn.iocoder.yudao.module.infra.api.ymconnection.dto.ConnectionPageReqDto;
import cn.iocoder.yudao.module.infra.api.ymconnection.dto.ConnectionRespDto;
import cn.iocoder.yudao.module.infra.api.ymconnection.dto.ConnectionSaveReqDto;
import cn.iocoder.yudao.module.infra.enums.TicketStatusEnum;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthRegisterReqVO;
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportExcelVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportRespVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.UserPostDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.dept.UserPostMapper;
import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMapper;
import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.system.service.dept.PostService;
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import cn.iocoder.yudao.module.system.service.permission.RoleService;
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.annotations.VisibleForTesting;
import com.mzt.logapi.context.LogRecordContext;
import com.mzt.logapi.service.impl.DiffParseFunction;
import com.mzt.logapi.starter.annotation.LogRecord;
import jakarta.annotation.Resource;
import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserDeptId;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.system.enums.LogRecordConstants.*;

/**
 * 后台用户 Service 实现类
 *
 * @author 芋道源码
 */
@Service("adminUserService")
@Slf4j
public class AdminUserServiceImpl implements AdminUserService {

    static final String USER_INIT_PASSWORD_KEY = "system.user.init-password";

    static final String USER_REGISTER_ENABLED_KEY = "system.user.register-enabled";

    @Resource
    private AdminUserMapper userMapper;
    @Resource
    private UserRoleMapper userRoleMapper;
    @Resource
    private DeptService deptService;
    @Resource
    private PostService postService;
    @Resource
    private PermissionService permissionService;
    @Resource
    private PasswordEncoder passwordEncoder;
    @Resource
    @Lazy // 延迟，避免循环依赖报错
    private TenantService tenantService;
    @Resource
    private RoleService roleService;
    @Resource
    private RoleMapper roleMapper;

    @Resource
    private UserPostMapper userPostMapper;

    @Resource
    private YmConnectionApi ymConnectionApi;

    @Resource
    private FileApi fileApi;
    @Resource
    private ConfigApi configApi;
    @Resource
    private AreaApi areaApi;
    @Resource
    private SiteApi siteApi;
    @Resource
    private TicketApi ticketApi;
    @Resource
    private MapUtilApi mapUtilApi;



    @Override
    public String getUsers(String ids) {
        List<AdminUserDO> adminUserDOS = userMapper.selectList();
        String names = "";
        if(ids != null && !"".equals(ids) ){
            for (String s : ids.split(",")) {
                if(!adminUserDOS.isEmpty()){
                    for (AdminUserDO adminUserDO : adminUserDOS) {
                        if(Long.parseLong(s) == adminUserDO.getId()){
                            names = names + adminUserDO.getNickname() + ",";
                        }
                    }
                }
            }
            if(names.length()>0){
                names = names.substring(0,names.length()-1);
            }
        }
        return names;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_CREATE_SUB_TYPE, bizNo = "{{#user.id}}",
            success = SYSTEM_USER_CREATE_SUCCESS)
    public Long createUser(UserSaveReqVO createReqVO) {
        // 1.1 校验账户配合
        tenantService.handleTenantInfo(tenant -> {
            long count = userMapper.selectCount();
            if (count >= tenant.getAccountCount()) {
                throw exception(USER_COUNT_MAX, tenant.getAccountCount());
            }
        });
        // 1.2 校验正确性
        validateUserForCreateOrUpdate(null, createReqVO.getUsername(),
                createReqVO.getMobile(), createReqVO.getEmail(), createReqVO.getDeptId(), createReqVO.getPostIds());
        // 2.1 插入用户
        AdminUserDO user = BeanUtils.toBean(createReqVO, AdminUserDO.class);
        user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
        user.setPassword(encodePassword(createReqVO.getPassword())); // 加密密码

        // 2.1.1插入默认头像
        String ymUserAvatar = configApi.getConfigValueByKey("ym_user_avatar");
        if(user.getAvatar() == null || user.getAvatar().isEmpty()){
            user.setAvatar(ymUserAvatar);
        }


        userMapper.insert(user);
        // 2.2 插入关联岗位
        if (CollectionUtil.isNotEmpty(user.getPostIds())) {
            userPostMapper.insertBatch(convertList(user.getPostIds(),
                    postId -> new UserPostDO().setUserId(user.getId()).setPostId(postId)));
        }

        // 2.3 插入关联角色
        if(createReqVO.getRoleIds() != null && !createReqVO.getRoleIds().isEmpty()){
            Set<Long> resultSet = Arrays.stream(createReqVO.getRoleIds().split(","))
                    .map(String::trim)  // 去除前后空格
                    .map(Long::parseLong)  // 转换为Long
                    .collect(Collectors.toSet());
            if(!resultSet.isEmpty()){
                permissionService.assignUserRole(user.getId(),resultSet);
            }
        }


        // 3. 记录操作日志上下文
        LogRecordContext.putVariable("user", user);

        // 4. 判断该用户是否绑定了 区域与电站
        String areaIds = createReqVO.getAreaIds(); //区域
        String siteIds = createReqVO.getSiteIds(); //电站
        List<ConnectionSaveReqDto> connectionSaveReqDtoList = getConnectionSaveReqDtos(areaIds, user, siteIds);
        if(!connectionSaveReqDtoList.isEmpty()){
            ymConnectionApi.insertBatch(connectionSaveReqDtoList);
        }
        return user.getId();
    }

    @Override
    public Long registerUser(AuthRegisterReqVO registerReqVO) {
        // 1.1 校验是否开启注册
        if (ObjUtil.notEqual(configApi.getConfigValueByKey(USER_REGISTER_ENABLED_KEY), "true")) {
            throw exception(USER_REGISTER_DISABLED);
        }
        // 1.2 校验账户配合
        tenantService.handleTenantInfo(tenant -> {
            long count = userMapper.selectCount();
            if (count >= tenant.getAccountCount()) {
                throw exception(USER_COUNT_MAX, tenant.getAccountCount());
            }
        });
        // 1.3 校验正确性
        validateUserForCreateOrUpdate(null, registerReqVO.getUsername(), null, null, null, null);

        // 2. 插入用户
        AdminUserDO user = BeanUtils.toBean(registerReqVO, AdminUserDO.class);
        user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
        user.setPassword(encodePassword(registerReqVO.getPassword())); // 加密密码
        userMapper.insert(user);
        return user.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
            success = SYSTEM_USER_UPDATE_SUCCESS)
    public void updateUser(UserSaveReqVO updateReqVO) {
        updateReqVO.setPassword(null); // 特殊：此处不更新密码
        // 1. 校验正确性
        AdminUserDO oldUser = validateUserForCreateOrUpdate(updateReqVO.getId(), updateReqVO.getUsername(),
                updateReqVO.getMobile(), updateReqVO.getEmail(), updateReqVO.getDeptId(), updateReqVO.getPostIds());

        // 2.1 更新用户
        AdminUserDO updateObj = BeanUtils.toBean(updateReqVO, AdminUserDO.class);
        userMapper.updateById(updateObj);
        // 2.2 更新岗位
        updateUserPost(updateReqVO, updateObj);
        // 2.3 判断是否修改了绑定区域以及绑定的电站
        String areaIds = updateReqVO.getAreaIds();
        String siteIds = updateReqVO.getSiteIds();
        //先删除所有有关的
        ymConnectionApi.deleteByUserId(updateObj.getId());
        List<ConnectionSaveReqDto> connectionSaveReqDtoList = getConnectionSaveReqDtos(areaIds, updateObj, siteIds);
        if(!connectionSaveReqDtoList.isEmpty()){
            ymConnectionApi.insertBatch(connectionSaveReqDtoList);
        }
        // 2.4 判断是否修改了角色
        String roleIds = updateReqVO.getRoleIds();
        //先删除所有有关的
        userRoleMapper.deleteListByUserId(updateObj.getId());
        if(roleIds != null && !roleIds.isEmpty()){
            Set<Long> resultSet = Arrays.stream(roleIds.split(","))
                    .map(String::trim)  // 去除前后空格
                    .map(Long::parseLong)  // 转换为Long
                    .collect(Collectors.toSet());
            if(!resultSet.isEmpty()){
                permissionService.assignUserRole(updateReqVO.getId(),resultSet);
            }
        }

        // 3. 记录操作日志上下文
        LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldUser, UserSaveReqVO.class));
        LogRecordContext.putVariable("user", oldUser);
    }

    /**
     * 插入关联表逻辑
     * @param areaIds
     * @param updateObj
     * @param siteIds
     * @return
     */
    private static List<ConnectionSaveReqDto> getConnectionSaveReqDtos(String areaIds, AdminUserDO updateObj, String siteIds) {
        List<ConnectionSaveReqDto> connectionSaveReqDtoList = new ArrayList<>();
        if(areaIds != null && !areaIds.isEmpty()){
            for (String areaId : areaIds.split(",")) {
                ConnectionSaveReqDto connectionSaveReqDto = new ConnectionSaveReqDto();
                connectionSaveReqDto.setPeopleId(updateObj.getId());
                connectionSaveReqDto.setThingId(Long.parseLong(areaId));
                connectionSaveReqDto.setType(1);
                connectionSaveReqDtoList.add(connectionSaveReqDto);
            }
        }
        if(siteIds != null && !siteIds.isEmpty()){
            for (String siteId : siteIds.split(",")) {
                ConnectionSaveReqDto connectionSaveReqDto = new ConnectionSaveReqDto();
                connectionSaveReqDto.setPeopleId(updateObj.getId());
                connectionSaveReqDto.setThingId(Long.parseLong(siteId));
                connectionSaveReqDto.setType(2);
                connectionSaveReqDtoList.add(connectionSaveReqDto);
            }
        }
        return connectionSaveReqDtoList;
    }

    private void updateUserPost(UserSaveReqVO reqVO, AdminUserDO updateObj) {
        Long userId = reqVO.getId();
        Set<Long> dbPostIds = convertSet(userPostMapper.selectListByUserId(userId), UserPostDO::getPostId);
        // 计算新增和删除的岗位编号
        Set<Long> postIds = CollUtil.emptyIfNull(updateObj.getPostIds());
        Collection<Long> createPostIds = CollUtil.subtract(postIds, dbPostIds);
        Collection<Long> deletePostIds = CollUtil.subtract(dbPostIds, postIds);
        // 执行新增和删除。对于已经授权的岗位，不用做任何处理
        if (!CollectionUtil.isEmpty(createPostIds)) {
            userPostMapper.insertBatch(convertList(createPostIds,
                    postId -> new UserPostDO().setUserId(userId).setPostId(postId)));
        }
        if (!CollectionUtil.isEmpty(deletePostIds)) {
            userPostMapper.deleteByUserIdAndPostId(userId, deletePostIds);
        }
    }

    @Override
    public void updateUserLogin(Long id, String loginIp) {
        userMapper.updateById(new AdminUserDO().setId(id).setLoginIp(loginIp).setLoginDate(LocalDateTime.now()));
    }

    @Override
    public void updateUserProfile(Long id, UserProfileUpdateReqVO reqVO) {
        // 校验正确性
        validateUserExists(id);
        validateEmailUnique(id, reqVO.getEmail());
        validateMobileUnique(id, reqVO.getMobile());
        // 执行更新
        userMapper.updateById(BeanUtils.toBean(reqVO, AdminUserDO.class).setId(id));
    }

    @Override
    public void updateUserPassword(Long id, UserProfileUpdatePasswordReqVO reqVO) {
        // 校验旧密码密码
        validateOldPassword(id, reqVO.getOldPassword());
        // 执行更新
        AdminUserDO updateObj = new AdminUserDO().setId(id);
        updateObj.setPassword(encodePassword(reqVO.getNewPassword())); // 加密密码
        userMapper.updateById(updateObj);
    }

    @Override
    public String updateUserAvatar(Long id, InputStream avatarFile) {
        validateUserExists(id);
        // 存储文件
        String avatar = fileApi.createFile(IoUtil.readBytes(avatarFile));
        // 更新路径
        AdminUserDO sysUserDO = new AdminUserDO();
        sysUserDO.setId(id);
        sysUserDO.setAvatar(avatar);
        userMapper.updateById(sysUserDO);
        return avatar;
    }

    @Override
    @LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_UPDATE_PASSWORD_SUB_TYPE, bizNo = "{{#id}}",
            success = SYSTEM_USER_UPDATE_PASSWORD_SUCCESS)
    public void updateUserPassword(Long id, String password) {
        // 1. 校验用户存在
        AdminUserDO user = validateUserExists(id);

        // 2. 更新密码
        AdminUserDO updateObj = new AdminUserDO();
        updateObj.setId(id);
        updateObj.setPassword(encodePassword(password)); // 加密密码
        userMapper.updateById(updateObj);

        // 3. 记录操作日志上下文
        LogRecordContext.putVariable("user", user);
        LogRecordContext.putVariable("newPassword", updateObj.getPassword());
    }

    @Override
    public void updateUserStatus(Long id, Integer status) {
        // 校验用户存在
        validateUserExists(id);
        // 更新状态
        AdminUserDO updateObj = new AdminUserDO();
        updateObj.setId(id);
        updateObj.setStatus(status);
        userMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_DELETE_SUB_TYPE, bizNo = "{{#id}}",
            success = SYSTEM_USER_DELETE_SUCCESS)
    public void deleteUser(Long id) {
        // 1. 校验用户存在
        AdminUserDO user = validateUserExists(id);

        // 2.1 删除用户
        userMapper.deleteById(id);
        // 2.2 删除用户关联数据
        permissionService.processUserDeleted(id);
        // 2.2 删除用户岗位
        userPostMapper.deleteByUserId(id);

        // 3. 记录操作日志上下文
        LogRecordContext.putVariable("user", user);
    }

    @Override
    public AdminUserDO getUserByUsername(String username) {
        return userMapper.selectByUsername(username);
    }

    @Override
    public AdminUserDO getUserByMobile(String mobile) {
        return userMapper.selectByMobile(mobile);
    }

    @Override
    public PageResult<AdminUserDO> getUserPage(UserPageReqVO reqVO) {
        //查询当前登录用户是否是管理员，负责只能查看本公司人员数据
        Long loginUserId = getLoginUserId();
        if(!handleAll(loginUserId)){
            Long loginUserDeptId = getLoginUserDeptId();
            reqVO.setDeptId(loginUserDeptId);
        }

        // 如果有角色编号，查询角色对应的用户编号
        Set<Long> roleUserIds = new HashSet<>();
        if(reqVO.getRoleId() != null){
            roleUserIds = permissionService.getUserRoleIdListByRoleId(singleton(reqVO.getRoleId()));
            if(roleUserIds.isEmpty()){ //如果是空的应该什么也搜不到，但是为空不会拼接条件会全部查出来，所以强制添加0保证查不出来
                roleUserIds.add(0L);
            }
        }
        // 如果有区域编号，查询区域对应的用户编号
        Set<Long> areaUserIds = new HashSet<>();
        if(reqVO.getAreaId() != null){
            areaUserIds = ymConnectionApi.getUserAreaIdListByAreaId(singleton(reqVO.getAreaId()));
            if(areaUserIds.isEmpty()){
                areaUserIds.add(0L);
            }
        }
        AreaSiteMapDto towMap = mapUtilApi.getTowMap();
        Map<Long, AreaDto> areaMap = towMap.areaMap;
        Map<Long, SiteDto> siteMap = towMap.siteMap;

        //获取某人工单的数量统计
        List<Map<Long, Object>> maps = ticketApi.allCount();
        //获取某人今天工单的数量统计
        List<Map<Long, Object>> maps1 = ticketApi.todayCount();


        //转换为map以便后续操作
        Map<Long, Long> resultMap = maps.stream()
                .collect(Collectors.toMap(
                        row -> (Long) row.get("operator_id"),
                        row -> (Long) row.get("count")
                ));
        Map<Long, Long> resultMap1 = maps1.stream()
                .collect(Collectors.toMap(
                        row -> (Long) row.get("operator_id"),
                        row -> (Long) row.get("count")
                ));


        // 分页查询
        PageResult<AdminUserDO> adminUserDOPageResult = userMapper.selectPage(reqVO, getDeptCondition(reqVO.getDeptId()), roleUserIds, areaUserIds);
        List<AdminUserDO> list = adminUserDOPageResult.getList();
        if(!list.isEmpty()){
            List<ConnectionRespDto> connectionList = ymConnectionApi.getConnectionList(new ConnectionPageReqDto());

            for (AdminUserDO adminUserDO : list) {

                //获取该人员的工单总数
                Long count = resultMap.get(adminUserDO.getId());
                //获取该人员今天的工单总数
                Long count1 = resultMap1.get(adminUserDO.getId());

                //为空是设置为0
                if (count == null) {
                    adminUserDO.setTicketCount(0L);
                }else {
                    adminUserDO.setTicketCount(count);
                }

                if (count1 == null) {
                    adminUserDO.setTodayTicketCount(0L);
                }else {
                    adminUserDO.setTodayTicketCount(count1);
                }

                String areaIds = "";
                String siteIds = "";
                if(!connectionList.isEmpty()){
                    for (ConnectionRespDto connectionRespDto : connectionList) {
                        if(Objects.equals(adminUserDO.getId(),connectionRespDto.getPeopleId())){
                            if(connectionRespDto.getType() == 1){ //区域
                                areaIds = areaIds + connectionRespDto.getThingId() + ",";
                            }else { //电站
                                siteIds = siteIds + connectionRespDto.getThingId() + ",";
                            }
                        }
                    }
                }
                if(!areaIds.isEmpty()){
                    areaIds = areaIds.substring(0,areaIds.length()-1);
                    adminUserDO.setAreaIds(areaIds);
                    List<String> areaNames = new ArrayList<>();
                    String[] split = areaIds.split(",");
                    if(areaMap != null){
                        for (String s1 : split) {
                            AreaDto areaDto = areaMap.get(Long.parseLong(s1));
                            if(areaDto != null){
                                areaNames.add(areaDto.getAreaName());
                            }
                        }
                    }
                    if(!areaNames.isEmpty()){
                        adminUserDO.setAreaNames(String.join(",", areaNames));
                    }
                }
                if(!siteIds.isEmpty()){
                    siteIds = siteIds.substring(0,siteIds.length()-1);
                    adminUserDO.setSiteIds(siteIds);
                    List<String> siteNames = new ArrayList<>();
                    String[] split = siteIds.split(",");
                    if(siteMap != null){
                        for (String s1 : split) {
                            SiteDto siteDto = siteMap.get(Long.parseLong(s1));
                            if(siteDto != null){
                                siteNames.add(siteDto.getSiteName());
                            }
                        }
                    }
                    if(!siteNames.isEmpty()){
                        adminUserDO.setSiteNames(String.join(",", siteNames));
                    }
                }

                List<UserRoleDO> userRoleDOS = userRoleMapper.selectListByUserId(adminUserDO.getId());
                if(!userRoleDOS.isEmpty()){
                    Set<Long> roleIds = userRoleDOS.stream()
                            .map(UserRoleDO::getRoleId)
                            .collect(Collectors.toSet());
                    // 转换并拼接
                    String result = roleIds.stream()
                            .map(Object::toString) // 将元素转为String
                            .collect(Collectors.joining(", "));
                    String roleNames = roleService.getRoleNames(roleIds);
                    adminUserDO.setRoleNames(roleNames);
                    adminUserDO.setRoleIds(result);
                }
            }
        }
        return adminUserDOPageResult;
    }

    // 判断当前用户是否 管理员
    public Boolean handleAll(Long userId){
        //判断当前用户得权限  如果是tenant_admin 则查看全部数据
        List<UserRoleDO> userRoleDOS = userRoleMapper.selectListByUserId(userId);
        if(userRoleDOS!= null && !userRoleDOS.isEmpty()){
            for (UserRoleDO userRoleDO : userRoleDOS) {
                Long roleId = userRoleDO.getRoleId();
                RoleDO roleDO = roleMapper.selectById(roleId);
                if(roleDO!=null && roleDO.getCode().equals("tenant_admin")){
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public AdminUserDO getUser(Long id) {
        AdminUserDO adminUserDO = userMapper.selectById(id);
        AreaSiteMapDto towMap = mapUtilApi.getTowMap();
        Map<Long, AreaDto> areaMap = towMap.areaMap;
        Map<Long, SiteDto> siteMap = towMap.siteMap;
        Optional.ofNullable(adminUserDO).ifPresent(a -> {
            ConnectionPageReqDto connectionPageReqDto = new ConnectionPageReqDto();
            connectionPageReqDto.setPeopleId(a.getId());
            List<ConnectionRespDto> connectionList = ymConnectionApi.getConnectionList(connectionPageReqDto);
            a.setConnectionRespDtoList(connectionList);
            String areaIds = "";
            String siteIds = "";
            if(!connectionList.isEmpty()){
                for (ConnectionRespDto connectionRespDto : connectionList) {
                    if(Objects.equals(a.getId(),connectionRespDto.getPeopleId())){
                        if(connectionRespDto.getType() == 1){ //区域
                            areaIds = areaIds + connectionRespDto.getThingId() + ",";
                        }else { //电站
                            siteIds = siteIds + connectionRespDto.getThingId() + ",";
                        }
                    }
                }
            }
            if(!areaIds.isEmpty()){
                areaIds = areaIds.substring(0,areaIds.length()-1);
                a.setAreaIds(areaIds);
                List<String> areaNames = new ArrayList<>();
                String[] split = areaIds.split(",");
                if(areaMap != null){
                    for (String s1 : split) {
                        AreaDto areaDto = areaMap.get(Long.parseLong(s1));
                        if(areaDto != null){
                            areaNames.add(areaDto.getAreaName());
                        }
                    }
                }
                if(!areaNames.isEmpty()){
                    a.setAreaNames(String.join(",", areaNames));
                }
            }
            if(!siteIds.isEmpty()){
                siteIds = siteIds.substring(0,siteIds.length()-1);
                a.setSiteIds(siteIds);
                List<String> siteNames = new ArrayList<>();
                String[] split = siteIds.split(",");
                if(siteMap != null){
                    for (String s1 : split) {
                        SiteDto siteDto = siteMap.get(Long.parseLong(s1));
                        if(siteDto != null){
                            siteNames.add(siteDto.getSiteName());
                        }
                    }
                }
                if(!siteNames.isEmpty()){
                    a.setSiteNames(String.join(",", siteNames));
                }
            }

            List<UserRoleDO> userRoleDOS = userRoleMapper.selectListByUserId(a.getId());
            if(!userRoleDOS.isEmpty()){
                Set<Long> roleIds = userRoleDOS.stream()
                        .map(UserRoleDO::getRoleId)
                        .collect(Collectors.toSet());
                String roleNames = roleService.getRoleNames(roleIds);
                a.setRoleNames(roleNames);
                // 转换并拼接
                String result = roleIds.stream()
                        .map(Object::toString) // 将元素转为String
                        .collect(Collectors.joining(", "));
                a.setRoleIds(result);
            }
            //获取这个人 待处理的工单 和 今日工单 和 处理中的工单
            long pendingCount = ticketApi.countByUserIdAndStatus(id, TicketStatusEnum.PENDING.getCode());
            long processingCount = ticketApi.countByUserIdAndStatus(id,TicketStatusEnum.PROCESSING.getCode());
            long todayCount = ticketApi.todayCountByUserId(id);
            a.setPendingTicketCount(pendingCount);
            a.setTodayTicketCount(todayCount);
            a.setProcessingTicketCount(processingCount);

        });

        return adminUserDO;
    }

    @Override
    public List<AdminUserDO> getUserListByDeptIds(Collection<Long> deptIds) {
        if (CollUtil.isEmpty(deptIds)) {
            return Collections.emptyList();
        }
        return userMapper.selectListByDeptIds(deptIds);
    }

    @Override
    public List<AdminUserDO> getUserListByPostIds(Collection<Long> postIds) {
        if (CollUtil.isEmpty(postIds)) {
            return Collections.emptyList();
        }
        Set<Long> userIds = convertSet(userPostMapper.selectListByPostIds(postIds), UserPostDO::getUserId);
        if (CollUtil.isEmpty(userIds)) {
            return Collections.emptyList();
        }
        return userMapper.selectBatchIds(userIds);
    }

    @Override
    public List<AdminUserDO> getUserList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }
        return userMapper.selectBatchIds(ids);
    }

    @Override
    public void validateUserList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return;
        }
        // 获得岗位信息
        List<AdminUserDO> users = userMapper.selectBatchIds(ids);
        Map<Long, AdminUserDO> userMap = CollectionUtils.convertMap(users, AdminUserDO::getId);
        // 校验
        ids.forEach(id -> {
            AdminUserDO user = userMap.get(id);
            if (user == null) {
                throw exception(USER_NOT_EXISTS);
            }
            if (!CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus())) {
                throw exception(USER_IS_DISABLE, user.getNickname());
            }
        });
    }

    @Override
    public List<AdminUserDO> getUserListByNickname(String nickname) {
        return userMapper.selectListByNickname(nickname);
    }

    /**
     * 获得公司条件：查询指定公司的子公司编号们，包括自身
     *
     * @param deptId 公司编号
     * @return 公司编号集合
     */
    private Set<Long> getDeptCondition(Long deptId) {
        if (deptId == null) {
            return Collections.emptySet();
        }
        Set<Long> deptIds = convertSet(deptService.getChildDeptList(deptId), DeptDO::getId);
        deptIds.add(deptId); // 包括自身
        return deptIds;
    }

    private AdminUserDO validateUserForCreateOrUpdate(Long id, String username, String mobile, String email,
                                               Long deptId, Set<Long> postIds) {
        // 关闭数据权限，避免因为没有数据权限，查询不到数据，进而导致唯一校验不正确
        return DataPermissionUtils.executeIgnore(() -> {
            // 校验用户存在
            AdminUserDO user = validateUserExists(id);
            // 校验用户名唯一
            validateUsernameUnique(id, username);
            // 校验手机号唯一
            validateMobileUnique(id, mobile);
            // 校验邮箱唯一
            validateEmailUnique(id, email);
            // 校验公司处于开启状态
            deptService.validateDeptList(CollectionUtils.singleton(deptId));
            // 校验岗位处于开启状态
            postService.validatePostList(postIds);
            return user;
        });
    }

    @VisibleForTesting
    AdminUserDO validateUserExists(Long id) {
        if (id == null) {
            return null;
        }
        AdminUserDO user = userMapper.selectById(id);
        if (user == null) {
            throw exception(USER_NOT_EXISTS);
        }
        return user;
    }

    @VisibleForTesting
    void validateUsernameUnique(Long id, String username) {
        if (StrUtil.isBlank(username)) {
            return;
        }
        AdminUserDO user = userMapper.selectByUsername(username);
        if (user == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的用户
        if (id == null) {
            throw exception(USER_USERNAME_EXISTS);
        }
        if (!user.getId().equals(id)) {
            throw exception(USER_USERNAME_EXISTS);
        }
    }

    @VisibleForTesting
    void validateEmailUnique(Long id, String email) {
        if (StrUtil.isBlank(email)) {
            return;
        }
        AdminUserDO user = userMapper.selectByEmail(email);
        if (user == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的用户
        if (id == null) {
            throw exception(USER_EMAIL_EXISTS);
        }
        if (!user.getId().equals(id)) {
            throw exception(USER_EMAIL_EXISTS);
        }
    }

    @VisibleForTesting
    void validateMobileUnique(Long id, String mobile) {
        if (StrUtil.isBlank(mobile)) {
            return;
        }
        AdminUserDO user = userMapper.selectByMobile(mobile);
        if (user == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的用户
        if (id == null) {
            throw exception(USER_MOBILE_EXISTS);
        }
        if (!user.getId().equals(id)) {
            throw exception(USER_MOBILE_EXISTS);
        }
    }

    /**
     * 校验旧密码
     * @param id          用户 id
     * @param oldPassword 旧密码
     */
    @VisibleForTesting
    void validateOldPassword(Long id, String oldPassword) {
        AdminUserDO user = userMapper.selectById(id);
        if (user == null) {
            throw exception(USER_NOT_EXISTS);
        }
        if (!isPasswordMatch(oldPassword, user.getPassword())) {
            throw exception(USER_PASSWORD_FAILED);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class) // 添加事务，异常则回滚所有导入
    public UserImportRespVO importUserList(List<UserImportExcelVO> importUsers, boolean isUpdateSupport) {
        // 1.1 参数校验
        if (CollUtil.isEmpty(importUsers)) {
            throw exception(USER_IMPORT_LIST_IS_EMPTY);
        }
        // 1.2 初始化密码不能为空
        String initPassword = configApi.getConfigValueByKey(USER_INIT_PASSWORD_KEY);
        if (StrUtil.isEmpty(initPassword)) {
            throw exception(USER_IMPORT_INIT_PASSWORD);
        }

        /**
         * 优化逻辑
         */
        List<RoleDO> roleDOS = roleMapper.selectList();
        // 正确转换方式
        Map<String, RoleDO> roleMap = Optional.ofNullable(roleDOS)
                .orElseGet(Collections::emptyList) // 处理null列表
                .stream()
                .filter(roleDo -> roleDo.getName() != null)
                .collect(Collectors.toMap(
                        RoleDO::getName,  // Key提取器
                        Function.identity(),  // Value提取器（对象本身）
                        (oldValue, newValue) -> oldValue  // 处理重复键：保留第一个值
                ));

        List<DeptDO> deptList = deptService.getDeptList(new DeptListReqVO());
        Map<String, DeptDO> deptMap = Optional.ofNullable(deptList)
                .orElseGet(Collections::emptyList) // 处理null列表
                .stream()
                .filter(deptDto -> deptDto.getName() != null)
                .collect(Collectors.toMap(
                        DeptDO::getName,  // Key提取器
                        Function.identity(),  // Value提取器（对象本身）
                        (oldValue, newValue) -> oldValue  // 处理重复键：保留第一个值
                ));
        AreaSiteNameMapDto towMap = mapUtilApi.getTwoMapByName();
        Map<String, SiteDto> siteMap = towMap.siteMap;
        Map<String, AreaDto> areaMap = towMap.areaMap;
        List<AdminUserDO> adminUserDOS = userMapper.selectList();
        Map<String, AdminUserDO> userMap = Optional.ofNullable(adminUserDOS)
                .orElseGet(Collections::emptyList) // 处理null列表
                .stream()
                .filter(userDO -> userDO.getUsername() != null)
                .collect(Collectors.toMap(
                        AdminUserDO::getUsername,  // Key提取器
                        Function.identity(),  // Value提取器（对象本身）
                        (oldValue, newValue) -> oldValue  // 处理重复键：保留第一个值
                ));


        // 2. 遍历，逐个创建 or 更新
        UserImportRespVO respVO = UserImportRespVO.builder().createUsernames(new ArrayList<>())
                .updateUsernames(new ArrayList<>()).failureUsernames(new LinkedHashMap<>()).build();
        // 需要插入的关联表数据
        List<ConnectionSaveReqDto> connectionSaveReqDtoList = new ArrayList<>();
        //需要更新的用户信息
        List<AdminUserDO> updateList = new ArrayList<>();

        importUsers.forEach(importUser -> {
            // 2.1.1 校验字段是否符合要求
            try {
                ValidationUtils.validate(BeanUtils.toBean(importUser, UserSaveReqVO.class).setPassword(initPassword));
                String deptName = importUser.getDeptName();
                if(deptName == null || deptName.isEmpty()){
                    respVO.getFailureUsernames().put(importUser.getUsername(), "人员公司不能为空");
                    return;
                }else {
                    DeptDO deptDO = deptMap.get(deptName);
                    if(deptDO == null){
                        respVO.getFailureUsernames().put(importUser.getUsername(),String.format("-公司 %s 不存在",deptName) );
                        return;
                    }else {
                        importUser.setDeptId(deptDO.getId());
                    }
                }

                String roleIds = importUser.getRoleIds();
                if(roleIds == null || roleIds.isEmpty()){
                    respVO.getFailureUsernames().put(importUser.getUsername(), "人员角色不能为空");
                    return;
                }else {
                    for (String s1 : roleIds.trim().split("\\|")) {
                        RoleDO roleDO = roleMap.get(s1);
                        if(roleDO == null){
                            respVO.getFailureUsernames().put(importUser.getUsername(),String.format("-角色 %s 不存在",s1) );
                            return;
                        }
                    }
                }

                String areaIds = importUser.getAreaIds();
                if(areaIds == null || areaIds.isEmpty()){
                    respVO.getFailureUsernames().put(importUser.getUsername(), "负责区域不能为空");
                    return;
                }else {
                    String[] split = areaIds.trim().split("\\|");
                    for (String s1 : split) {
                        AreaDto areaDto = areaMap.get(s1);
                        if(areaDto == null){
                            respVO.getFailureUsernames().put(importUser.getUsername(),String.format("-系统暂无该区域-%s", s1));
                            return;
                        }
                    }
                }
                String siteIds = importUser.getSiteIds();
                if(siteIds != null && !siteIds.isEmpty()){
                    String[] split = siteIds.trim().split("\\|");
                    for (String s1 : split) {
                        SiteDto byId = siteMap.get(s1);
                        if(byId == null){
                            respVO.getFailureUsernames().put(importUser.getUsername(),String.format("-系统暂无该电站-%s", s1));
                            return;
                        }else{
                            String areaName = byId.getAreaName();
                            List<String> resultList = Arrays.stream(areaIds.split("\\|"))
                                    .map(String::trim)  // 去除前后空格
                                    .map(Object::toString)
                                    .collect(Collectors.toList());
                            if(!resultList.contains(areaName)){
                                respVO.getFailureUsernames().put(importUser.getUsername(), String.format("系统暂无与 %s 电站绑定的区域",s1));
                                return;
                            }
                        }
                    }
                }
            } catch (ConstraintViolationException ex){
                respVO.getFailureUsernames().put(importUser.getUsername(), ex.getMessage());
                return;
            }

            // 2.2.1 判断如果不存在，在进行插入
            AdminUserDO existUser = userMap.get(importUser.getUsername());

            if (existUser == null) {

                // 校验，判断是否有不符合的原因
                try {
                    validateUserForCreateOrUpdate(null, null, importUser.getMobile(), null,
                            null, null);
                } catch (ServiceException ex) {
                    respVO.getFailureUsernames().put(importUser.getUsername(), ex.getMessage());
                    return;
                }
                // 插入默认头像
                String ymUserAvatar = configApi.getConfigValueByKey("ym_user_avatar");
                userMapper.insert(BeanUtils.toBean(importUser, AdminUserDO.class)
                        .setPassword(encodePassword(initPassword)).setPostIds(new HashSet<>()).setAvatar(ymUserAvatar)); // 设置默认密码及空岗位编号数组

                AdminUserDO adminUserDO = userMapper.selectByUsername(importUser.getUsername());

                //2.2.1.2 如果不存在，需要在关联表增加记录

                String areaIds = importUser.getAreaIds();
                String siteIds = importUser.getSiteIds();
                String roleIds = importUser.getRoleIds();
                if(areaIds != null && !areaIds.isEmpty()){
                    for (String s1 : areaIds.trim().split("\\|")) {
                        AreaDto idByName = areaMap.get(s1);
                        Optional.ofNullable(idByName).ifPresent(a -> {
                            ConnectionSaveReqDto connectionSaveReqDto = new ConnectionSaveReqDto();
                            connectionSaveReqDto.setType(1);
                            connectionSaveReqDto.setPeopleId(adminUserDO.getId());
                            connectionSaveReqDto.setThingId(a.getId());
                            connectionSaveReqDtoList.add(connectionSaveReqDto);
                        });
                    }
                }
                if(siteIds != null && !siteIds.isEmpty()){
                    for (String s1 : siteIds.trim().split("\\|")) {
                        SiteDto idByName = siteMap.get(s1);
                        Optional.ofNullable(idByName).ifPresent(a -> {
                            ConnectionSaveReqDto connectionSaveReqDto = new ConnectionSaveReqDto();
                            connectionSaveReqDto.setType(2);
                            connectionSaveReqDto.setPeopleId(adminUserDO.getId());
                            connectionSaveReqDto.setThingId(a.getId());
                            connectionSaveReqDtoList.add(connectionSaveReqDto);
                        });
                    }
                }
                if(roleIds != null && !roleIds.isEmpty()){
                    String roleIdsByNames = roleService.getRoleIdsByNames(roleIds);
                    if(roleIdsByNames != null && !roleIdsByNames.isEmpty()){
                        Set<Long> resultSet = Arrays.stream(roleIdsByNames.trim().split("\\|"))
                                .map(String::trim)  // 去除前后空格
                                .map(Long::parseLong)  // 转换为Long
                                .collect(Collectors.toSet());
                        if(!resultSet.isEmpty()){
                            permissionService.assignUserRole(adminUserDO.getId(),resultSet);
                        }
                    }
                }
//                respVO.getCreateUsernames().add(importUser.getUsername());
                respVO.getCreateUsernames().add("1");
                return;
            }
            // 2.2.2 如果存在，判断是否允许更新
            if (!isUpdateSupport) {
                respVO.getFailureUsernames().put(importUser.getUsername(), USER_USERNAME_EXISTS.getMsg());
                return;
            }
            // 校验，判断是否有不符合的原因
            try {
                validateUserForCreateOrUpdate(existUser.getId(), null, importUser.getMobile(), null,
                        null, null);
            } catch (ServiceException ex) {
                respVO.getFailureUsernames().put(importUser.getUsername(), ex.getMessage());
                return;
            }


            AdminUserDO updateUser = BeanUtils.toBean(importUser, AdminUserDO.class);
            updateUser.setId(existUser.getId());
            updateList.add(updateUser);
//            respVO.getUpdateUsernames().add(importUser.getUsername());
            respVO.getUpdateUsernames().add("1");
        });

        //批量插入关联表
        if(!connectionSaveReqDtoList.isEmpty()){
            ymConnectionApi.insertBatch(connectionSaveReqDtoList);
        }
        //批量更新用户
        if(!updateList.isEmpty()){
            userMapper.updateBatch(updateList);
        }

        return respVO;
    }

    @Override
    public List<AdminUserDO> getUserListByStatus(Integer status) {
        List<AdminUserDO> adminUserDOS = userMapper.selectListByStatus(status);

        if(!adminUserDOS.isEmpty()){
            List<ConnectionRespDto> connectionList = ymConnectionApi.getConnectionList(new ConnectionPageReqDto());
            AreaSiteMapDto towMap = mapUtilApi.getTowMap();
            Map<Long, AreaDto> areaMap = towMap.areaMap;
            Map<Long, SiteDto> siteMap = towMap.siteMap;
            for (AdminUserDO adminUserDO : adminUserDOS) {
                String areaIds = "";
                String siteIds = "";
                if(!connectionList.isEmpty()){
                    for (ConnectionRespDto connectionRespDto : connectionList) {
                        if(Objects.equals(adminUserDO.getId(),connectionRespDto.getPeopleId())){
                            if(connectionRespDto.getType() == 1){ //区域
                                areaIds = areaIds + connectionRespDto.getThingId() + ",";
                            }else { //电站
                                siteIds = siteIds + connectionRespDto.getThingId() + ",";
                            }
                        }
                    }
                }
                if(!areaIds.isEmpty()){
                    areaIds = areaIds.substring(0,areaIds.length()-1);
                    adminUserDO.setAreaIds(areaIds);
                    List<String> areaNames = new ArrayList<>();
                    String[] split = areaIds.split(",");
                    if(areaMap != null){
                        for (String s1 : split) {
                            AreaDto areaDto = areaMap.get(Long.parseLong(s1));
                            if(areaDto != null){
                                areaNames.add(areaDto.getAreaName());
                            }
                        }
                    }
                    if(!areaNames.isEmpty()){
                        adminUserDO.setAreaNames(String.join(",", areaNames));
                    }
                }
                if(!siteIds.isEmpty()){
                    siteIds = siteIds.substring(0,siteIds.length()-1);
                    adminUserDO.setSiteIds(siteIds);
                    List<String> siteNames = new ArrayList<>();
                    String[] split = siteIds.split(",");
                    if(siteMap != null){
                        for (String s1 : split) {
                            SiteDto siteDto = siteMap.get(Long.parseLong(s1));
                            if(siteDto != null){
                                siteNames.add(siteDto.getSiteName());
                            }
                        }
                    }
                    if(!siteNames.isEmpty()){
                        adminUserDO.setSiteNames(String.join(",", siteNames));
                    }
                }
                List<UserRoleDO> userRoleDOS = userRoleMapper.selectListByUserId(adminUserDO.getId());
                if(!userRoleDOS.isEmpty()){
                    Set<Long> roleIds = userRoleDOS.stream()
                            .map(UserRoleDO::getRoleId)
                            .collect(Collectors.toSet());
                    String roleNames = roleService.getRoleNames(roleIds);
                    adminUserDO.setRoleNames(roleNames);
                    // 转换并拼接
                    String result = roleIds.stream()
                            .map(Object::toString) // 将元素转为String
                            .collect(Collectors.joining(", "));
                    adminUserDO.setRoleIds(result);
                }
            }
        }
        return adminUserDOS;
    }

    @Override
    public boolean isPasswordMatch(String rawPassword, String encodedPassword) {
        return passwordEncoder.matches(rawPassword, encodedPassword);
    }

    /**
     * 对密码进行加密
     *
     * @param password 密码
     * @return 加密后的密码
     */
    private String encodePassword(String password) {
        return passwordEncoder.encode(password);
    }

    //获取用户的总工单和今日工单数
    public PageResult<UserPageReqVO> getTicketCount(UserPageReqVO reqVO){

        List<AdminUserDO> adminUserDOS = userMapper.selectList();

        List<UserPageReqVO> bean = BeanUtils.toBean(adminUserDOS, UserPageReqVO.class);

        //获取某人工单的数量统计
        List<Map<Long, Object>> maps = ticketApi.allCount();
        //获取某人今天工单的数量统计
        List<Map<Long, Object>> maps1 = ticketApi.todayCount();


        //转换为map以便后续操作
        Map<Long, Long> resultMap = maps.stream()
                .collect(Collectors.toMap(
                        row -> (Long) row.get("operator_id"),
                        row -> (Long) row.get("count")
                ));
        Map<Long, Long> resultMap1 = maps1.stream()
                .collect(Collectors.toMap(
                        row -> (Long) row.get("operator_id"),
                        row -> (Long) row.get("count")
                ));


        for (UserPageReqVO userPageReqVO : bean) {
            //获取该人员的工单总数
            Long count = resultMap.get(userPageReqVO.getId());
            //获取该人员今天的工单总数
            Long count1 = resultMap1.get(userPageReqVO.getId());


            //为空是设置为0
            if (count == null) {
                userPageReqVO.setTicketCount(0L);
            }else {
                userPageReqVO.setTicketCount(count);
            }



            if (count1 == null) {
                userPageReqVO.setTodayTicketCount(0L);
            }else {
                userPageReqVO.setTodayTicketCount(count1);
            }

        }
        //对list进行分页
        PageResult<UserPageReqVO> result = new PageResult<>();
        result.setList(bean);
        result.setTotal((long) bean.size());
        return result;
    }

}
